package demo.java.awt;

import demo.excel.PoiDemo;
import org.junit.Test;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Properties;

public class ImageDemo {

    /**
     * 根据key读取value
     *
     * @param filePath
     * @param keyWord
     * @return
     * @return String
     * @throws
     * @Title: getProperties
     * @Description: 使用缓冲输入流读取配置文件，然后将其加载，再按需操作
     * 绝对路径或相对路径， 如果是相对路径，则从当前项目下的目录开始计算，
     * 如：当前项目路径/config/config.properties,
     * 相对路径就是config/config.properties
     */
    public static String getProperties(String filePath, String keyWord) {
        Properties prop = new Properties();
        String value = null;
        try {
            // 通过输入缓冲流进行读取配置文件
            InputStream InputStream = new BufferedInputStream(new FileInputStream(new File(filePath)));
            // 加载输入流
            prop.load(InputStream);
            // 根据关键字获取value值
            value = prop.getProperty(keyWord);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 镜像处理 180°水平和垂直翻转
     * type = 0 表示上下翻转，type = 1 表示左右翻转
     *
     * @param bufferedimage 需要翻转的BufferedImage对象
     * @param type
     * @return
     */
    public static BufferedImage imageMisro(BufferedImage bufferedimage, int type) {
        try {
            int w = bufferedimage.getWidth();
            int h = bufferedimage.getHeight();

            int[][] datas = new int[w][h];
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    // getRGB 获取图像中的像素整数值 二进制格式
                    datas[j][i] = bufferedimage.getRGB(j, i);
                }
            }
            int[][] tmps = new int[w][h];
            if (type == 0) {
                for (int i = 0, a = h - 1; i < h; i++, a--) {
                    for (int j = 0; j < w; j++) {
                        tmps[j][a] = datas[j][i];
                    }
                }
            } else if (type == 1) {
                for (int i = 0; i < h; i++) {
                    for (int j = 0, b = w - 1; j < w; j++, b--) {
                        tmps[b][i] = datas[j][i];
                    }
                }
            }
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    bufferedimage.setRGB(j, i, tmps[j][i]);
                }
            }


            return bufferedimage;
            //ImageIO.write(bufferedimage, "jpg", file);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * content 需要绘制的文字
     * interval 文字两端空余像素
     * fontSize 文字大小
     * x 绘制起始点x
     * y 绘制起始点y
     * g2 graphics2D对象
     */
    public static void drawWord(String content, int fontSize, float x, float y, Graphics2D g2) {
        //消除文字锯齿
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2.setPaint(Color.BLACK);
        g2.setFont(new Font("仿宋", Font.BOLD, fontSize));

        g2.drawString(content, x, y); // 文字画入画布中
    }

    public static void exportImage(int width, int height, List<PoiDemo.Grid> grids, String formatName, String outputPath) throws IOException {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();

        graphics.setColor(Color.white);
        graphics.fillRect(0, 0, width, height);
        // 平滑字体
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST, 140);
        graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        // 绘制表格
        for (PoiDemo.Grid g : grids) {
            if (!g.isShow()) {
                continue;
            }
            // 绘制背景色
            graphics.setColor(g.getBgColor() == null ? Color.white : g.getBgColor());
            graphics.fillRect(g.getX(), g.getY(), g.getWidth(), g.getHeight());

            // 绘制边框
            graphics.setColor(Color.black);
            graphics.setStroke(new BasicStroke(1));
            graphics.drawRect(g.getX(), g.getY(), g.getWidth(), g.getHeight());

            // 绘制文字,居中显示
            graphics.setColor(g.getFtColor());
            Font font = g.getFont();
            if (font == null) {
                continue;
            }
            FontMetrics fm = graphics.getFontMetrics(font);
            int strWidth = fm.stringWidth(g.getText());// 获取将要绘制的文字宽度
            graphics.setFont(font);
            graphics.drawString(g.getText(), g.getX() + (g.getWidth() - strWidth) / 2,
                    g.getY() + (g.getHeight() - font.getSize()) / 2 + font.getSize());
        }
        //表格最后一行有可能不显示，手动画上一行
        graphics.drawLine(0, height - 1, width - 4, height - 1);

        graphics.dispose();
        ImageIO.write(image, formatName, new File(outputPath));
    }

    public void demo() throws IOException {
        int width = 500, height = 500;
        //创建图片对象
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
        //基于图片对象打开绘图
        Graphics2D g2 = image.createGraphics();

        // 常用的前置设置(不设置线段/文字不是横竖（就是斜的）的时候会有锯齿)
        //消除文字锯齿
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //声明并创建矩形对象，矩形的左上角是(20，30)，宽是300，高是40
        Rectangle2D back = new Rectangle2D.Double(20, 30, 300, 40);
        g2.fill(back);

        //声明并创建圆对象，矩形的左上角是(20，30)，宽是100，高是100
        Ellipse2D.Double ellipse = new Ellipse2D.Double(20, 20, 100, 100);
        g2.draw(ellipse);

        // 创建线段，参数就是两个点的xy坐标   x1,y1,x2,y2
        Line2D.Float line = new Line2D.Float(10, 10, 20, 20);

//        绘制 - 基本常用的就是draw（绘制边线） fill（填充：填充内容根据前置设置而定）

        // 前置可以进行线条粗细、字体大小、画笔颜色等属性的设置
        // 设置画笔颜色
        g2.setColor(Color.WHITE);
        // 设置画笔粗细
        Stroke stroke = new BasicStroke(2.0f);//设置线宽为2.0
        g2.setStroke(stroke);
        // 设置字体大小
        g2.setFont(new Font("仿宋", Font.BOLD, 5));
        // 绘制文字 content-内容  xy坐标
        // 文字画入画布中
        drawWord("文字内容", 3, 0, 0, g2);
        // 直接放入图形对象
        g2.draw(null);
        // 可以写入本地文件（文件名无路径默认/src下）
        //保存图片 JPG表示保存格式
        ImageIO.write(image, "JPEG", new FileOutputStream("a.jpg"));
        ImageIO.write(image, "png", new File("abcd.png"));


    }

    /**
     * 绘制多边形
     *
     * @param pointList 多边形的坐标集
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    public BufferedImage drawPolygon(List<Point> pointList) throws FileNotFoundException, IOException {
        //得到图片缓冲区
        BufferedImage image = new BufferedImage
                //INT精确度达到一定,RGB三原色,宽度512，高度512
                (1000, 600, BufferedImage.TYPE_INT_RGB);

        //得到它的绘制环境(这张图片的笔)
        Graphics2D g2 = (Graphics2D) image.getGraphics();

        //消除文字锯齿
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //设置画笔白色
        g2.setColor(Color.white);
        //全图填充白色底图
        g2.fillRect(0, 0, image.getWidth(), image.getHeight());

        //shape的子类，表示一个形状
        GeneralPath gp = new GeneralPath();
        // 确定两个点
        Point p1 = pointList.remove(0);
        Point p2 = pointList.remove(0);

        //两个点画第一条直线
        gp.append(new
                Line2D.Double(p1.getX(), p1.getY(), p2.getX(), p2.getY()), true);
        //直线分别与余下的点相连
        for (Point point : pointList) {
            gp.lineTo(point.getX(), point.getY());
        }
        //闭合图形
        gp.closePath();
        //设置画笔黑色
        g2.setColor(Color.BLACK);

        // 填充网格- 填充内容来自图片
        image = fillPolygon(image, gp);
        //填充图形
        g2.draw(gp);

        // 翻转图形 - 上下翻转180°
//        image = imageMisro(image,UPSIDE_DOWN);

        // 释放g2资源
        g2.dispose();


//        ImageIO.write(image,"JPEG",new FileOutputStream("a.jpg"));//保存图片 				JPEG表示保存格式
//        ImageIO.write(image, "png", new File("abcd.png"));
        return image;
    }

    /**
     * 填充不规则多边形 - 固定填充 src/main/resources/img/fillImg2.jpg
     *
     * @param image BufferedImage对象
     * @param gp    多边形
     * @return
     * @throws IOException
     */
    private BufferedImage fillPolygon(BufferedImage image, GeneralPath gp) throws IOException {

        // 0.读取配置文件
        String url = getProperties("src/main/resources/fill-Img.properties", "fill-img.url");
        System.out.println("url:" + url);
        // 1.得到它的绘制环境(这张图片的笔)
        Graphics2D g2 = (Graphics2D) image.getGraphics();
        // 2.填充网格- 填充内容来自图片
        BufferedImage fillImg = ImageIO.read(new File(url));  //要填充图片
        // 创建矩形（用来放图片的框）
        Rectangle2D examp = new Rectangle2D.Double(100, 100, 50, 50);
        // 把图片填充进矩形（矩形大小就是上面矩形的大小） -》 制作成画笔
        TexturePaint tp = new TexturePaint(fillImg, examp); //Rectangle2D是img大小
        g2.setPaint(tp);//设置g2的画笔为图片样式的
        g2.fill(gp);//gp不规则图形
        return image;
    }

    /**
     * fillOval
     * 此方法，用来在一个矩形区域中填充一个圆形底色。
     *
     * @throws IOException
     */
    @Test
    public void testFillOval() throws IOException {
        String path = "/Users/xmly/Documents/tmp/testPng.png";
        BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = image.createGraphics();
        graphics2D.fillOval(0, 0, 500, 500);
        ImageIO.write(image, "png", Files.newOutputStream(Paths.get(path)));
    }

    /**
     * fillArc
     * 此方法，用来填充矩形或者圆形状的底色，其实这里和我们平时见到的饼状图差不多。
     *
     * @throws IOException
     */
    @Test
    public void testFillArc() throws IOException {
        String path = "/Users/xmly/Documents/tmp/testPng.png";
        BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = image.createGraphics();
        graphics2D.fillArc(0, 0, 500, 500, 10, 30);
        ImageIO.write(image, "png", Files.newOutputStream(Paths.get(path)));
    }

    /**
     * fillRect 用来填充矩形形状的底色
     *
     * @throws IOException
     */
    @Test
    public void testFillRect() throws IOException {
        String path = "/Users/xmly/Documents/tmp/testPng.png";
        BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = image.createGraphics();
        graphics2D.fillRect(0, 0, 310, 335);
        ImageIO.write(image, "png", Files.newOutputStream(Paths.get(path)));
    }

    /**
     * java.awt.Color 转换为16进制字符串
     *
     * @param color
     * @return
     */
    public static String toHex(Color color) {
        String hex = String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue());
        System.out.println(color + " ==> " + hex);
        return hex;
    }

    @Test
    public void testColor() {
        System.out.println(toHex(Color.RED));
        System.out.println(toHex(Color.GREEN));
        System.out.println(toHex(Color.BLUE));
    }


}
